package com.aw.baselib.net.api;

import com.aw.baselib.R;
import com.aw.baselib.base.AwBaseApplication;
import com.aw.baselib.base.AwBaseConstant;
import com.aw.baselib.net.RequestBase;
import com.aw.baselib.net.SSLSocketClient;
import com.aw.baselib.util.AwDataUtil;
import com.aw.baselib.util.AwLog;

import java.io.File;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.util.concurrent.TimeUnit;

import androidx.annotation.NonNull;
import okhttp3.Cache;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;

/**
 * @author : hzw
 */

public class Okhttp3Manager {

    /** 网络请求重试，请求时间间隔 */
    public static final long NET_RETRY_INTERVAL = 500;
    //设置缓存目录
    private static File cacheDirectory = new File(AwBaseApplication.getInstance().getApplicationContext().getCacheDir().getAbsolutePath(), "MyCache");
    private static Cache cache = new Cache(cacheDirectory, 10 * 1024 * 1024);

    public static OkHttpClient.Builder getOkhttp() {
        UrlInterceptor requestParamInterceptor = new UrlInterceptor();
        OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
        httpClient.connectTimeout(60, TimeUnit.SECONDS);
        httpClient.readTimeout(60, TimeUnit.SECONDS);
        httpClient.writeTimeout(60, TimeUnit.SECONDS);
        //        httpClient.retryOnConnectionFailure(true);
        httpClient.addInterceptor(logging());
        httpClient.addInterceptor(new RetryInterceptor());
        httpClient.addNetworkInterceptor(requestParamInterceptor);
        httpClient.sslSocketFactory(SSLSocketClient.getSSLSocketFactory());
        httpClient.hostnameVerifier(SSLSocketClient.getHostnameVerifier());
        httpClient.cache(cache);//设置缓存
        //加入拦截器
        //        RequestParamInterceptor requestParamInterceptor = new RequestParamInterceptor();
        //        httpClient.addNetworkInterceptor(requestParamInterceptor);
        //加入https的证书
  /*      int[] certficates = new int[]{R.raw.app_key};
        SSLSocketFactory sslSocketFactory = getSSLSocketFactory(AppContext.getContext(), certficates);
        if (sslSocketFactory != null) {
            httpClient.sslSocketFactory(sslSocketFactory);
        }
*/
        return httpClient;
    }

    //OKHttpClient 请求库的日志管理配置
    @NonNull
    private static Interceptor logging() {
        HttpLoggingInterceptor logging = new HttpLoggingInterceptor(message -> {
            AwLog.d("okhttp", message);
        });
        logging.setLevel(HttpLoggingInterceptor.Level.BODY);
        if(AwLog.is_Loggable) {
            logging.setLevel(HttpLoggingInterceptor.Level.BODY);
        } else {
            logging.setLevel(HttpLoggingInterceptor.Level.NONE);
        }
        return logging;
    }

    /**
     * @Desc   重试 拦截器，默认所有白名单外的网络请求，全部重试3次
     * @parame
     * @return
     */
    private static class RetryInterceptor implements Interceptor{

        public RetryInterceptor() {

        }

        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            Response response = doRequest(chain, request);
            int retryNum = 0;
            //判断请求路径是否在过滤清单中，如果在，则直接返回相应，不做重试请求处理
            if(AwBaseConstant.NET_RETRY_FILTER_LIST .length > 0){
                for(String urlFilter : AwBaseConstant.NET_RETRY_FILTER_LIST){
                    if(request!= null && request.url().url().toString().contains(urlFilter)){
                        return response;
                    }
                }
            }
            //默认循环请求3次，成功即终止
            while ((response == null || !response.isSuccessful()) && retryNum < AwBaseConstant.NET_REQUEST_MAX_RETRY_COUNT) {
                try {
                    AwLog.d("属于网络异常，重试中，第"+retryNum + "次");
                    Thread.sleep(NET_RETRY_INTERVAL);
                } catch (final InterruptedException e) {
                    Thread.currentThread().interrupt();
                    throw new InterruptedIOException();
                }
                retryNum++;
                // retry the request
                response = doRequest(chain, request);
            }
            return response;
        }

        private Response doRequest(Chain chain, Request request) {
            Response response = null;
            try {
                response = chain.proceed(request);
            } catch (Exception e) {
            }
            return response;
        }
    }

    public static void getRequest(String url, OkhttpCallback callback) {
        Request request = new Request.Builder()
                //                .cacheControl(CacheControl.FORCE_NETWORK) //取消缓存读取
                .method("GET", null)
                .url(url)
                .build();
        Call mcall = getOkhttp().build().newCall(request);
        mcall.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                AwLog.d("getRequest onFailure........");
                if(AwDataUtil.isEmpty(e.getMessage())) {
                    callback.onFail(AwBaseApplication.getInstance().getString(R.string.common_net_server_abnormal));
                } else {
                    callback.onFail(e.getMessage());
                }
            }

            @Override
            public void onResponse(Call call, Response response) {
                AwLog.d("getRequest onResponse........");
                if(response.isSuccessful()) {
                    try {
                        callback.onSuccess(response.body().string());
                    } catch (IOException e) {
                        e.printStackTrace();
                        callback.onFail("response parse exception");
                    }
                } else {
                    callback.onFail(AwBaseApplication.getInstance().getString(R.string.common_net_server_abnormal));
                }

            }
        });
    }

    public static void postRequest(String url, RequestBody body, OkhttpCallback callback) {
        if(body == null) {
            body = RequestBase.getBody();
        }
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        Call call = getOkhttp().build().newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                AwLog.d("getRequest onFailure........");
                callback.onFail(e.getMessage());
            }

            @Override
            public void onResponse(Call call, Response response)  {
                AwLog.d("postRequest onResponse........");
                if(response.isSuccessful()) {
                    try {
                        callback.onSuccess(response.body().string());
                    } catch (IOException e) {
                        e.printStackTrace();
                        callback.onFail(e.getMessage());
                    }
                } else {
                    callback.onFail(AwBaseApplication.getInstance().getString(R.string.common_net_server_abnormal));
                }
            }

        });
    }

    public interface OkhttpCallback {
        void onSuccess(String str);
        void onFail(String msg);
    }
}

